package org.jeecg.modules.crm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.crm.entity.CrmContact;
import org.jeecg.modules.crm.entity.CrmCustomer;
import org.jeecg.modules.crm.entity.CrmProject;
import org.jeecg.modules.crm.entity.vo.CrmCustomerVO;
import org.jeecg.modules.crm.mapper.CrmCustomerMapper;
import org.jeecg.modules.crm.service.ICrmContactService;
import org.jeecg.modules.crm.service.ICrmCustomerService;
import org.jeecg.modules.crm.service.ICrmProjectService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description: 客户信息
 * @Author: jeecg-boot
 * @Date:   2023-06-03
 * @Version: V1.0
 */
@Service
public class CrmCustomerServiceImpl extends ServiceImpl<CrmCustomerMapper, CrmCustomer> implements ICrmCustomerService {

    private static final Logger log = LoggerFactory.getLogger(CrmCustomerServiceImpl.class);

    @Autowired
    private ICrmContactService contactService;
    
    @Autowired
    private ICrmProjectService projectService;

    /**
     * 生成客户编号
     * 格式：KH + 年月日 + 4位序号
     * @return 新生成的客户编号
     */
    public String generateCustomerCode() {
        String datePrefix = "KH" + java.time.LocalDate.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMdd"));
        
        try {
            log.info("开始生成客户编号，日期前缀: {}", datePrefix);
            
            // 查询当天最大编号
            QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
            queryWrapper.likeRight("customer_code", datePrefix);
            queryWrapper.orderByDesc("customer_code");
            queryWrapper.last("limit 1");
            CrmCustomer customer = getOne(queryWrapper);
            
            int sequence = 1;
            if (customer != null && customer.getCustomerCode() != null) {
                String currentCode = customer.getCustomerCode();
                log.info("找到当天最大客户编号: {}", currentCode);
                try {
                    sequence = Integer.parseInt(currentCode.substring(datePrefix.length())) + 1;
                } catch (Exception e) {
                    log.error("解析客户编号序列号失败: {}, 将使用默认序号 1", e.getMessage());
                    sequence = 1;
                }
            } else {
                log.info("当天尚无客户编号记录，将使用序号 1");
            }
            
            String newCode = datePrefix + String.format("%04d", sequence);
            log.info("成功生成客户编号: {}", newCode);
            return newCode;
        } catch (Exception e) {
            log.error("生成客户编号过程中发生错误: {}", e.getMessage());
            // 确保即使出错也能返回一个可用的编号
            return datePrefix + String.format("%04d", System.currentTimeMillis() % 10000);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveCustomerVO(CrmCustomerVO customerVO) {
        // 保存客户信息
        log.info("开始保存客户信息: {}", customerVO.getCustomerName());
        
        // 自动生成客户编号
        if (customerVO.getCustomerCode() == null || customerVO.getCustomerCode().trim().isEmpty()) {
            customerVO.setCustomerCode(generateCustomerCode());
            log.info("已自动生成客户编号: {}", customerVO.getCustomerCode());
        }
        
        // 检查客户名称和联系人组合的唯一性
        if (!checkCustomerNameAndContactUnique(customerVO)) {
            throw new RuntimeException("客户名称和联系人组合已存在，请检查后重试");
        }
        
        boolean saved = save(customerVO);
        
        if (saved) {
            String customerId = customerVO.getId();
            log.info("客户信息保存成功，ID: {}", customerId);
            
            // 保存联系人信息
            List<CrmContact> contacts = customerVO.getContactList();
            if (contacts != null && !contacts.isEmpty()) {
                log.info("开始保存客户联系人信息，联系人数量: {}", contacts.size());
                for (CrmContact contact : contacts) {
                    contact.setCustomerId(customerId);
                    // 确保新增联系人没有ID
                    if (contact.getId() == null || contact.getId().trim().isEmpty()) {
                        contact.setId(null);
                    }
                }
                contactService.saveBatch(contacts);
            }
            
            // 保存项目信息
            List<CrmProject> projects = customerVO.getProjectList();
            if (projects != null && !projects.isEmpty()) {
                log.info("开始保存客户项目信息，项目数量: {}", projects.size());
                for (CrmProject project : projects) {
                    project.setCustomerId(customerId);
                    // 确保新增项目没有ID
                    if (project.getId() == null || project.getId().trim().isEmpty()) {
                        project.setId(null);
                    }
                }
                projectService.saveBatch(projects);
            }
        } else {
            log.error("客户信息保存失败");
        }
        
        return saved;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCustomerVO(CrmCustomerVO customerVO) {
        String customerId = customerVO.getId();
        if (customerId == null || customerId.trim().isEmpty()) {
            log.error("更新客户信息失败：客户ID为空");
            return false;
        }
        
        // 检查客户是否存在
        CrmCustomer existingCustomer = getById(customerId);
        if (existingCustomer == null) {
            log.error("更新客户信息失败：客户不存在，ID: {}", customerId);
            return false;
        }
        
        // 检查客户名称和联系人组合的唯一性（排除当前客户）
        if (!checkCustomerNameAndContactUnique(customerVO)) {
            throw new RuntimeException("客户名称和联系人组合已存在，请检查后重试");
        }
        
        log.info("开始更新客户信息: {}, ID: {}", customerVO.getCustomerName(), customerId);
        
        // 更新客户信息
        boolean updated = updateById(customerVO);
        
        if (updated) {
            log.info("客户基本信息更新成功");
            
            // 处理联系人信息
            List<CrmContact> contacts = customerVO.getContactList();
            // 先删除原有联系人
            log.info("删除客户原有联系人信息");
            contactService.deleteByCustomerId(customerId);
            
            if (contacts != null && !contacts.isEmpty()) {
                log.info("保存更新后的联系人信息，联系人数量: {}", contacts.size());
                for (CrmContact contact : contacts) {
                    contact.setCustomerId(customerId);
                    // 确保联系人没有ID或ID为空字符串时设置为null
                    if (contact.getId() == null || contact.getId().trim().isEmpty()) {
                        contact.setId(null);
                    }
                }
                contactService.saveBatch(contacts);
            }
            
            // 处理项目信息
            List<CrmProject> projects = customerVO.getProjectList();
            if (projects != null && !projects.isEmpty()) {
                log.info("处理项目信息，项目数量: {}", projects.size());
                for (CrmProject project : projects) {
                    project.setCustomerId(customerId);
                    if (project.getId() != null && !project.getId().trim().isEmpty()) {
                        log.info("更新项目信息: {}", project.getProjectName());
                        projectService.updateById(project);
                    } else {
                        log.info("新增项目信息: {}", project.getProjectName());
                        project.setId(null); // 确保ID为null以便新增
                        projectService.save(project);
                    }
                }
            }
        } else {
            log.error("客户信息更新失败");
        }
        
        return updated;
    }
    
    /**
     * 检查客户名称和联系人组合的唯一性
     * @param customerVO 客户信息
     * @return 是否唯一
     */
    private boolean checkCustomerNameAndContactUnique(CrmCustomerVO customerVO) {
        if (customerVO == null || customerVO.getCustomerName() == null || customerVO.getContactPerson() == null) {
            return false; // 如果没有提供客户名称或联系人，不允许保存
        }
        
        String customerName = customerVO.getCustomerName().trim();
        String contactPerson = customerVO.getContactPerson().trim();
        
        log.info("检查客户名称和联系人组合的唯一性: {}，{}", customerName, contactPerson);
        
        // 构建查询条件
        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("customer_name", customerName)
                   .eq("contact_person", contactPerson)
                   .eq("del_flag", 0); // 只检查未删除的客户
        
        // 如果是更新操作，排除当前客户
        if (customerVO.getId() != null && !customerVO.getId().isEmpty()) {
            queryWrapper.ne("id", customerVO.getId());
        }
        
        Long count = count(queryWrapper);
        
        if (count > 0) {
            log.warn("客户名称和联系人组合已存在: {}，{}", customerName, contactPerson);
            return false;
        }
        
        return true;
    }

    @Override
    public CrmCustomerVO getCustomerVOById(String id) {
        // 获取客户信息
        CrmCustomer customer = getById(id);
        if (customer == null) {
            return null;
        }
        
        CrmCustomerVO customerVO = new CrmCustomerVO();
        org.springframework.beans.BeanUtils.copyProperties(customer, customerVO);
        
        // 获取联系人信息
        List<CrmContact> contacts = contactService.getContactsByCustomerId(id);
        customerVO.setContactList(contacts);
        
        // 获取项目信息
        List<CrmProject> projects = projectService.getProjectsByCustomerId(id);
        customerVO.setProjectList(projects);
        
        // 设置主联系人
        if (contacts != null && !contacts.isEmpty()) {
            customerVO.setPrimaryContact(contacts.get(0));
        }
        
        return customerVO;
    }

    @Override
    public IPage<CrmCustomer> selectCustomerPage(Page<CrmCustomer> page, CrmCustomer customer) {
        return baseMapper.selectCustomerPage(page, customer);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteCustomerById(String id) {
        // 逻辑删除客户信息
        CrmCustomer customer = new CrmCustomer();
        customer.setId(id);
        customer.setDelFlag(1);
        boolean result = updateById(customer);
        
        if (result) {
            // 删除关联的联系人
            contactService.deleteByCustomerId(id);
            
            // 删除关联的项目
            projectService.deleteByCustomerId(id);
        }
        
        return result;
    }

    @Override
    public List<CrmCustomer> getSuggestCustomerList(String keyword, Integer limit) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        keyword = keyword.trim();
        log.info("执行客户智能提示查询，关键字: {}", keyword);
        
        // 构建查询条件
        QueryWrapper<CrmCustomer> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("customer_name", keyword)
                   .or().like("customer_code", keyword)
                   .or().like("contact_person", keyword)
                   .eq("del_flag", 0) // 未删除的数据
                   .orderByDesc("create_time")
                   .last("limit " + limit);
        
        return baseMapper.selectList(queryWrapper);
    }
    
    @Override
    public List<Map<String, Object>> getSuggestContactList(String keyword, Integer limit) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        keyword = keyword.trim();
        log.info("执行联系人智能提示查询，关键字: {}", keyword);
        
        // 这里调用联系人表进行查询
        return contactService.getSuggestContactList(keyword, limit);
    }
    
    @Override
    public List<Map<String, Object>> checkCustomerSimilarity(CrmCustomerVO customerVO) {
        if (customerVO == null || customerVO.getCustomerName() == null || customerVO.getCustomerName().trim().isEmpty()) {
            return new ArrayList<>();
        }
        
        String customerName = customerVO.getCustomerName().trim();
        log.info("执行客户相似度检查，客户名称: {}", customerName);
        
        List<Map<String, Object>> result = new ArrayList<>();
        
        // 1. 精确匹配客户名称
        QueryWrapper<CrmCustomer> exactWrapper = new QueryWrapper<>();
        exactWrapper.eq("customer_name", customerName)
                   .eq("del_flag", 0);
        List<CrmCustomer> exactMatches = baseMapper.selectList(exactWrapper);
        
        for (CrmCustomer customer : exactMatches) {
            Map<String, Object> item = new HashMap<>();
            item.put("customer", customer);
            item.put("similarity", 100); // 100% 匹配
            item.put("matchType", "exact"); // 精确匹配
            result.add(item);
        }
        
        // 2. 模糊匹配 - 首先是包含关系
        if (result.isEmpty()) {
            QueryWrapper<CrmCustomer> containWrapper = new QueryWrapper<>();
            containWrapper.like("customer_name", customerName)
                         .eq("del_flag", 0);
            List<CrmCustomer> containMatches = baseMapper.selectList(containWrapper);
            
            for (CrmCustomer customer : containMatches) {
                // 计算相似度 - 使用最长公共子序列算法
                int similarity = calculateSimilarity(customerName, customer.getCustomerName());
                if (similarity >= 60) { // 只返回相似度大于60%的
                    Map<String, Object> item = new HashMap<>();
                    item.put("customer", customer);
                    item.put("similarity", similarity);
                    item.put("matchType", "contain");
                    result.add(item);
                }
            }
        }
        
        // 3. 查找去除空格和特殊字符后匹配的记录
        if (result.isEmpty()) {
            String normalizedName = normalizeText(customerName);
            List<CrmCustomer> allCustomers = baseMapper.selectList(
                new QueryWrapper<CrmCustomer>().eq("del_flag", 0));
            
            for (CrmCustomer customer : allCustomers) {
                String normalizedCustomerName = normalizeText(customer.getCustomerName());
                // 计算相似度
                int similarity = calculateSimilarity(normalizedName, normalizedCustomerName);
                if (similarity >= 70) { // 只返回相似度大于70%的
                    Map<String, Object> item = new HashMap<>();
                    item.put("customer", customer);
                    item.put("similarity", similarity);
                    item.put("matchType", "normalized");
                    result.add(item);
                }
            }
        }
        
        // 按相似度排序
        result.sort((a, b) -> ((Integer) b.get("similarity")).compareTo((Integer) a.get("similarity")));
        
        // 限制返回数量
        if (result.size() > 10) {
            result = result.subList(0, 10);
        }
        
        return result;
    }
    
    /**
     * 计算两个字符串的相似度
     * @param str1 字符串1
     * @param str2 字符串2
     * @return 相似度百分比
     */
    private int calculateSimilarity(String str1, String str2) {
        if (str1 == null || str2 == null) {
            return 0;
        }
        
        // 使用编辑距离(Levenshtein Distance)算法
        int len1 = str1.length();
        int len2 = str2.length();
        
        int[][] dp = new int[len1 + 1][len2 + 1];
        
        for (int i = 0; i <= len1; i++) {
            dp[i][0] = i;
        }
        
        for (int j = 0; j <= len2; j++) {
            dp[0][j] = j;
        }
        
        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = Math.min(dp[i - 1][j - 1] + 1, Math.min(dp[i][j - 1] + 1, dp[i - 1][j] + 1));
                }
            }
        }
        
        int maxLen = Math.max(len1, len2);
        int distance = dp[len1][len2];
        return (int) (((maxLen - distance) / (double) maxLen) * 100);
    }
    
    /**
     * 标准化文本，去除空格和特殊字符
     * @param text 原始文本
     * @return 标准化后的文本
     */
    private String normalizeText(String text) {
        if (text == null) {
            return "";
        }
        
        // 移除空格和标点符号，转为小写
        return text.replaceAll("[\\s\\p{P}]", "").toLowerCase();
    }
} 